﻿#include "Mario.h"

const float offset = 0.01f;
const float jumpoffset = 1.f;
const float gravity = 20.f;

CMario::CMario(void)
{

}

CMario::CMario(int i)
{
	int j = i;
}

CMario::CMario(float x, float y, int Width, int Height, float vx, float vy, int deltaTime, LPD3DXSPRITE spriteHandler, LPDIRECT3DTEXTURE9 image):
	MObject(x, y, Width, Height, vx, vy, deltaTime, spriteHandler, image)
{
	this->_sprite = shared_ptr<Sprite>(new Sprite("MarioDefault",spriteHandler,Width,Height,1,1,image,10));
}

CMario::CMario(float x, float y, float vx, float vy, int deltaTime,int resourceName, CResourceManager *rm):MObject(x,y,vx,vy,deltaTime,resourceName,rm)
{
	this->_objectType = CResourceManager::TYPE_MARIO1;
	_maxvx = 0.5f;
	_lastDir = DIR_RIGHT;

	_status = STATUS_ALIVE;
	_extraVy = 0;

	_allowJump = true;

	_spriteStandRight1 = _rm->getSprite(CResourceManager::MARIOSTANDRIGHT1);
	_spriteMoveLeft1 = _rm->getSprite(CResourceManager::MARIOMOVELEFT1);
	_spriteMoveRight1 = _rm->getSprite(CResourceManager::MARIOMOVERIGHT1);
	_spriteJumpLeft1 = _rm->getSprite(CResourceManager::MARIOJUMPLEFT1);
	_spriteJumpRight1 = _rm->getSprite(CResourceManager::MARIOJUMPRIGHT1);
	_spriteStandLeft1 = _rm->getSprite(CResourceManager::MARIOSTANDLEFT1);
	_spriteDie = _rm->getSprite(CResourceManager::MARIODIE);

	_spriteStandRight2 = _rm->getSprite(CResourceManager::MARIOSTANDRIGHT2);
	_spriteMoveLeft2 = _rm->getSprite(CResourceManager::MARIOMOVELEFT2);
	_spriteMoveRight2 = _rm->getSprite(CResourceManager::MARIOMOVERIGHT2);
	_spriteJumpLeft2 = _rm->getSprite(CResourceManager::MARIOJUMPLEFT2);
	_spriteJumpRight2 = _rm->getSprite(CResourceManager::MARIOJUMPRIGHT2);
	_spriteStandLeft2 = _rm->getSprite(CResourceManager::MARIOSTANDLEFT2);

	_spriteStandRight3 = _rm->getSprite(CResourceManager::MARIOSTANDRIGHT3);
	_spriteMoveLeft3 = _rm->getSprite(CResourceManager::MARIOMOVELEFT3);
	_spriteMoveRight3 = _rm->getSprite(CResourceManager::MARIOMOVERIGHT3);
	_spriteJumpLeft3 = _rm->getSprite(CResourceManager::MARIOJUMPLEFT3);
	_spriteJumpRight3 = _rm->getSprite(CResourceManager::MARIOJUMPRIGHT3);
	_spriteStandLeft3 = _rm->getSprite(CResourceManager::MARIOSTANDLEFT3);

	_immortalTime = 0;
	_life = 4;
	_coin = 0;
	_score = 0;

	_teleport = Vector();
	_inNewRoom = false;

}


CMario::~CMario(void)
{
}

//Hàm di chuyển
void CMario::Move()
{
	switch (_status)
	{
	case STATUS_CHANGINGLEVEL:
	case STATUS_ALIVE:
		{
			_lastX = _x;
			_lastY = _y;

			int w,h;
			_sprite->getSize(w,h);
			float t1 = this->getLastTranslateVector().getY();
			float t2 = this->getVelocityVector().getY();
			float ty = t1 + t2;

			if ((_isFalling == false && _isJumping != true) || _isJumping != true && ((this->getLastTranslateVector() != Vector() &&(ty<=0))))
			{
				_vy = 0;
			}
			else
				if (_vy < 2.f)
   					_vy += 0.12f;

			_x= _x + (_vx)*_deltaTime;
			_y= _y + (_vy + _extraVy)*_deltaTime;

			if (_y > 600) 
			{
				_y = 600;
				_level = 1;
				setStatus(STATUS_DYING);
				break;
			}

			if (_x < 0)
				_x = 0;

			if (!_inNewRoom)
			{
				if (_x < 400)
					CScreen::setPosition(0,0);
				else if (_x > _xEndMap + 400)
				{
					CScreen::setPosition(this->_xEndMap,0);
				}
				else
					CScreen::setPosition(_x - 400,0);
			}


			//Kiểm tra trạng thái của Mario để xác định sprite tương ứng
			int status = this->getMarioStatus();

			switch(status)
			{ 
				case IS_STANDING:
					{
						if (_lastDir == DIR_LEFT)
							_sprite = _spriteStandLeft;
						else 
							_sprite = _spriteStandRight;
						break;
					}
				case IS_MOVING_LEFT:
					{
						_sprite = _spriteMoveLeft;
						break;
					}
				case IS_MOVING_RIGHT:
				{
					_sprite = _spriteMoveRight;
					break;
				}
				case IS_FLYING:
					{
						if (_lastDir == DIR_LEFT)
							_sprite = _spriteJumpLeft;
						else 
							_sprite = _spriteJumpRight;
						break;
					}
			} 
			if (_vx > 0.05f)
			{
				_lastDir = DIR_RIGHT;
				_vx -= 0.05f;
			}
			else if (_vx < - 0.05f)
			{
				_vx += 0.05f;
				_lastDir = DIR_LEFT;
				}
				else _vx = 0;
			_lastTranslateVector = Vector();
			_extraVy = 0;
			if (_vy > 0) _isJumping = false;

			if (_delayMove > 0)
				_delayMove --;

			if (_status == STATUS_CHANGINGLEVEL)
			{
				_immortalTime --;
				if (_immortalTime == 0)
				{
					setStatus(STATUS_ALIVE);
				}
			}
			break;
		}
	case STATUS_DYING:
		{
			if (_dieDelayTime > 0)
				_dieDelayTime--;
			else
			{
				_vy += 0.2f;
				_y += _vy*_deltaTime;
				if (_y > 600)
					setStatus(STATUS_DEAD);
			}
			break;
		}
	case STATUS_TOPIPE:
		{
			_y += _vy*_deltaTime;
			_slideTime --;
			if (_slideTime <= 0)
			{
				Teleport(_teleport.getX(),_teleport.getY());
				setStatus(STATUS_OUTPIPE);
			}
			break;
		}
	case STATUS_OUTPIPE:
		{
			_y -= _vy*_deltaTime;
			_slideTime--;
			if (_slideTime <= 0)
			{
				setStatus(STATUS_ALIVE);
			}
			
			break;
		}

	case STATUS_MOVENEXTMAP:
		{
			_lastX = _x;
			_lastY = _y;

			int w,h;
			_sprite->getSize(w,h);
			float t1 = this->getLastTranslateVector().getY();
			float t2 = this->getVelocityVector().getY();
			float ty = t1 + t2;

			if ((_isFalling == false && _isJumping != true) || _isJumping != true && ((this->getLastTranslateVector() != Vector() &&(ty<=0))))
			{
				_vy = 0;
			}
			else
				if (_vy < 2.f)
   					_vy += 0.12f;

			_x= _x + (_vx)*_deltaTime;
			_y= _y + (_vy + _extraVy)*_deltaTime;

			if (!_inNewRoom)
			{
				if (_x < 400)
					CScreen::setPosition(0,0);
				else if (_x > _xEndMap + 400)
				{
					CScreen::setPosition(this->_xEndMap,0);
				}
				else
					CScreen::setPosition(_x - 400,0);
			}


			int status = this->getMarioStatus();


			switch(status)
			{ 
				case IS_STANDING:
					{
						if (_lastDir == DIR_LEFT)
							_sprite = _spriteStandLeft;
						else 
							_sprite = _spriteStandRight;
						break;
					}
				case IS_MOVING_LEFT:
					{
						_sprite = _spriteMoveLeft;
						break;
					}
				case IS_MOVING_RIGHT:
				{
					_sprite = _spriteMoveRight;
					break;
				}
				case IS_FLYING:
					{
						if (_lastDir == DIR_LEFT)
							_sprite = _spriteJumpLeft;
						else 
							_sprite = _spriteJumpRight;
						break;
					}
			} 
			
			_lastTranslateVector = Vector();
			_extraVy = 0;
			if (_vy > 0) _isJumping = false;

			if (_status == STATUS_CHANGINGLEVEL)
			{
				_immortalTime --;
				
				if (_immortalTime == 0)
					setStatus(STATUS_ALIVE);
			}
			break;
		}
	}
}

void CMario::MoveLeft()
{
	if (_delayMove > 0) return;
	if (_vx > 0)
		_vx = 0.f;
	if (_vx > -_maxvx)
			_vx -= 0.05f;
	_isMoving = true;
}

void CMario::MoveRight()
{
	if (_delayMove > 0) return;

	if (_vx < 0)
		_vx = 0.f;
		if (_vx < _maxvx)
			_vx += 0.05f;
	_isMoving = true;

}

void CMario::Render()
{
	if (!(_immortalTime > 0 && _immortalTime % 4 != 0))
	{
		Vector v;
		v = CScreen::getPosition();
		this->_sprite->Render(this->_x - v.getX(),this->_y - v.getY());
	}
}

void CMario::Jump()	
{
	if (_vy == 0 && _allowJump)
	{
		_vy = -1.55f;
		_isJumping = true;
	}
}

int CMario::getMarioStatus()
{
	if (abs(_lastY - _y) >= 1.8f)
		return IS_FLYING;
	else
		if (_vx > 0)
		{
			_lastDir = DIR_RIGHT;
			return IS_MOVING_RIGHT;
		}
		else if (_vx < 0)
			{
				_lastDir = DIR_LEFT;
				return IS_MOVING_LEFT;
			}
			else return IS_STANDING;
}

RECT CMario::getRect()
{
	int width,height;
	_sprite->getSize(width,height);

	RECT rec;
	rec.left = _x + 2.f;
	rec.top = _y;
	rec.right = rec.left + width - 2.f;
	rec.bottom = rec.top + height;

	return rec;
}

void CMario::setVelocity(Vector v, shared_ptr<MObject> Object)
{
	if (_lastTranslateVector.getX() == 0 && _lastTranslateVector.getY() < 0)
	{
		if (Object->getObjectType() == CResourceManager::TYPE_MUSHROOM || Object->getObjectType() == CResourceManager::TYPE_TURTLE);
	}
	_vx = v.getX();
	_vy = v.getY();
}

//xử lý hành vi của Mario sau khi va chạm
//Direction: hướng va chạm
//Object: đối tượng mà mario va chạm với
void CMario::actAfterCollided(int Direction, shared_ptr<MObject> Object)
{
	if (Object->getObjectType() == CResourceManager::TYPE_FOOD)
	{
		_score += 200;
		setLevel(_level + 1,true);
	}

	if ((Direction == 3 || Direction == 4))
		_delayMove = 2;
	switch (Direction)
	{
		case 1: //UP
			{
				break;
			}
		case 2: //DOWN
		case 3: //RIGHT
		case 4: //LEFT
			{
				if (_status != STATUS_CHANGINGLEVEL && (Object->getObjectType() == CResourceManager::TYPE_MUSHROOM || (Object->getObjectType() == CResourceManager::TYPE_TURTLE && !(Object->getStatus() == Turtle::STATUS_PUSHED && Object->getVelocityVector().getX() == 0))) && _y >= Object->getPosition().getY() - 30)
					setStatus(STATUS_DYING);
				break;
			}
	}
}

void CMario::setStatus(int Status)
{
	_status = Status;
	switch (_status)
	{

	case STATUS_MOVENEXTMAP:
		{
			_vx = _maxvx;
			CMarioSound::getInstance()->Stop(CMarioSound::SOUND_BACKGROUND);
			CMarioSound::getInstance()->Play(CMarioSound::SOUND_LEVELCOMPLETE,false);
			break;
		}
	case STATUS_ALIVE:
		{
			break;
		}

	case STATUS_DYING:
		{
			if (_level == 1)
			{
				_sprite = _spriteDie;
				_vy = -2.f;
				_dieDelayTime = 10;

				if (_life > 0)
					{
						_life--;
						if (_life > 0)
							CMarioSound::getInstance()->Play(CMarioSound::SOUND_DIE,false);
							else 
							{
								CMarioSound::getInstance()->Stop(CMarioSound::SOUND_BACKGROUND);
								CMarioSound::getInstance()->Play(CMarioSound::SOUND_GAMEOVER,false);
							}
					}
				
				break;
			}
			else
				setLevel(1,true);
			break;
		}

	case STATUS_CHANGINGLEVEL:
		{
			_immortalTime = 50;
			break;
		}
	case STATUS_TOPIPE:
		{
			_vx = 0;
			_vy = 0.06f;
			if (_level == 1)
				_slideTime = 35;
			else
				_slideTime = 55;
			break;
		}
	case STATUS_OUTPIPE:
		{
			if (_inNewRoom)
				CScreen::getInstance()->setPosition(_newRoomPos.getX(),_newRoomPos.getY());
			else
			{
				if (_x < 400)
				CScreen::setPosition(0,0);
			else
				CScreen::setPosition(_x - 400,0);
			}

			_vx = 0;
			_vy = 0.06f;
			if (_level == 1)
				_slideTime = 35;
			else
				_slideTime = 55;
			break;
		}
	}
}

void CMario::setLevel(int level, bool Flash)
{
	if (level > 3) level = 3;

	if (level == 1 && _level > 1)
		_y += 30;
	else 
		if (level >1 && _level == 1)
			_y -= 30;
	setSprite(level);
	if (level < _level)
		CMarioSound::getInstance()->Play(CMarioSound::SOUND_BONUSAPPEARED,false);

	_level = level;

	if (Flash)
	{
		setStatus(STATUS_CHANGINGLEVEL);
	}

}

void CMario::setSprite(int level)
{
	_currentSpriteLevel = level;
	switch (level)
	{
	case 1:
		{
				_status = STATUS_ALIVE;
				_spriteStandRight = _spriteStandRight1;
				_spriteMoveLeft = _spriteMoveLeft1;
				_spriteMoveRight = _spriteMoveRight1;
				_spriteJumpLeft = _spriteJumpLeft1;
				_spriteJumpRight = _spriteJumpRight1;
				_spriteStandLeft = _spriteStandLeft1;
			break;
		}

	case 2:
		{
				_spriteStandRight = _spriteStandRight2;
				_spriteMoveLeft = _spriteMoveLeft2;
				_spriteMoveRight = _spriteMoveRight2;
				_spriteJumpLeft = _spriteJumpLeft2;
				_spriteJumpRight = _spriteJumpRight2;
				_spriteStandLeft = _spriteStandLeft2;
			break;
		}

	case 3:
		{
				_spriteStandRight = _spriteStandRight3;
				_spriteMoveLeft = _spriteMoveLeft3;
				_spriteMoveRight = _spriteMoveRight3;
				_spriteJumpLeft = _spriteJumpLeft3;
				_spriteJumpRight = _spriteJumpRight3;
				_spriteStandLeft = _spriteStandLeft3;
			break;
		}
	}
}

